/**
 * 1 必须是类
 * 2 必须有apply函数
 * 3 必须调用 compiler api影响打包结果
 * 
 * 是一个独立的模块。
 * 模块对外暴露一个 js 函数。
 * 函数的原型 (prototype) 上定义了一个注入 compiler 对象的 apply 方法。
 * apply 函数中需要有通过 compiler 对象挂载的 webpack 事件钩子，钩子的回调中能拿到当前编译的 compilation 对象，如果是异步编译插件的话可以拿到回调 callback。
 * 完成自定义子编译流程并处理 complition 对象的内部数据。
 * 如果异步编译插件的话，数据处理完成后执行 callback 回调。
 */

class RemoveCommentPlugin {
  // opts 是 new 的时候传递的参数
  constructor(opts) {
    this.opts = opts;
    this.externalModules = {};
  }
  apply(compiler) {
    // entryOption : 在 webpack 选项中的 entry 配置项 处理过之后，执行插件。
    // afterPlugins : 设置完初始插件之后，执行插件。
    // compilation : 编译创建之后，生成文件之前，执行插件。。
    // emit : 生成资源到 output 目录之前。
    // done : 编译完成。
    // 注册自定义插件钩子到生成资源到 output 目录之前，拿到compilation对象（编译好的stream） tap 同步打包 tapAsync 异步打包
    compiler.hooks.emit.tap("RemoveCommentPlugin", (compilation) => {
      // 遍历构建产物
      Object.keys(compilation.assets).forEach((item) => {
        // .source() 是获取构建产物的文本
        // .assets 中包含构建产物的文件名
        let content = compilation.assets[item].source();
        content = content.replace("blue", "red"); // 将第一个blue替换为red
        // 更新构建产物对象
        compilation.assets[item] = {
          source: () => content,
          size: () => content.length,
        };
      });
    });
  }
}

module.exports = RemoveCommentPlugin;
